package code;

import java.util.ArrayList;
import java.util.List;

public class Simulator {
	private static boolean debug = true;
	public static void simulate(double probability,int numOfFloors,int numOfElevators, int simulationLength){
		int requestNum = 0;
		int totalWait = 0;
		RequestQueue requestQueue = new RequestQueue();
		List<Elevator> elevatorList = new ArrayList<Elevator>();
		BooleanSource boolSource = new BooleanSource(probability);
		for(int i=0;i<numOfElevators;i++){
			elevatorList.add(new Elevator());
		}
		for(int i=1;i<=simulationLength;i++){
			Request request = null;
			if(boolSource.requestArrived()){
				request = new Request(numOfFloors);
				request.setTimeEntered(i);
				requestQueue.enqueue(request);
			}
			
			for(Elevator elevator : elevatorList){
				if(elevator.getElevatorState()  == Elevator.IDLE){
					if(requestQueue.isEmpty()){
						continue;
					}
					Request requestForElevator = null;
					try {
						requestForElevator = requestQueue.dequeue();
						elevator.setRequest(requestForElevator);
					} catch (EmptyQueueWhenDequeueException e) {
						e.printStackTrace();
					}
					if(requestForElevator.getSourceFloor() == elevator.getCurrentFloor()){
						requestNum++;
						totalWait = totalWait + (i-requestForElevator.getTimeEntered());
						elevator.setElevatorState(Elevator.TO_DESTINATION);
						if(requestForElevator.getDestinationFloor() == elevator.getCurrentFloor()){
							elevator.setElevatorState(Elevator.IDLE);
							elevator.setRequest(null);
						}else
						if(requestForElevator.getDestinationFloor() > elevator.getCurrentFloor()){
							elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
						}else
						if(requestForElevator.getDestinationFloor() < elevator.getCurrentFloor()){
							elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
						}
					}else{
						elevator.setElevatorState(Elevator.TO_SOURCE);
						if(requestForElevator.getSourceFloor() > elevator.getCurrentFloor()){
							elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
						}else
						if(requestForElevator.getSourceFloor() < elevator.getCurrentFloor()){
							elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
						}
					}
					
				}else
				if(elevator.getElevatorState()  == Elevator.TO_SOURCE){
					if(elevator.getRequest().getSourceFloor() == elevator.getCurrentFloor()){
						elevator.setElevatorState(Elevator.TO_DESTINATION);
						requestNum++;
						totalWait = totalWait + (i-elevator.getRequest().getTimeEntered()) ;
						if(elevator.getRequest().getDestinationFloor() == elevator.getCurrentFloor()){
							elevator.setElevatorState(Elevator.IDLE);
							elevator.setRequest(null);
						}else{
							if(elevator.getRequest().getDestinationFloor()>elevator.getCurrentFloor()){
								elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
							}else{
								elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
							}
							if(elevator.getRequest().getDestinationFloor() == elevator.getCurrentFloor()){
								elevator.setElevatorState(Elevator.IDLE);
								elevator.setRequest(null);
							}
						}
					}else{
						if(elevator.getRequest().getSourceFloor() > elevator.getCurrentFloor()){
							elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
						}else{
							elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
						}
					}
					
				}else
				if(elevator.getElevatorState()  == Elevator.TO_DESTINATION){
					if(elevator.getRequest().getDestinationFloor() > elevator.getCurrentFloor()){
						elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
					}else
					if(elevator.getRequest().getDestinationFloor() < elevator.getCurrentFloor()){
						elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
					}
					
					if(elevator.getRequest().getDestinationFloor() == elevator.getCurrentFloor()){
						elevator.setElevatorState(Elevator.IDLE);
						elevator.setRequest(null);
					}
				}
			}
			
			if(debug){
				if(request == null){
					System.out.println("Step "+i+" : "+"Nothing Arrives");
					System.out.println("Requests:");
				}else{
					System.out.println("Step "+i+" : "+request.getDesc());
					System.out.println("Requests:"+request.toString());
				}
				System.out.print("Elevators: ");
				int j=0;
				for(j=0;j<elevatorList.size()-1;j++){
					System.out.print(elevatorList.get(j)+", ");
				}
				System.out.println(elevatorList.get(j));
			}
		}

		System.out.println("Total Wait Time: "+totalWait);
		System.out.println("Total Requests: "+requestNum);
		if(requestNum==0){
			System.out.println("Average Wait Time: "+String.format("%.2f",totalWait/(requestNum+0.0)));
		}else{
			System.out.println("Average Wait Time: "+String.format("%.2f",totalWait/(requestNum+0.0)));
		}
		
	}
}
